﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Web;
using UDS.Components;

namespace UDS.Entity
{
    /// <summary>
    /// 指定流程跳转规则
    /// </summary>
    public enum FlowRule
    {
        /// <summary>
        /// 按人员
        /// </summary>
        [DisplayName("按人员")]
        Staff = 0,

        /// <summary>
        /// 按职位
        /// </summary>
        [DisplayName("按职位")]
        Position = 1,

        /// <summary>
        /// 按项目
        /// </summary>
        [DisplayName("按项目")]
        Project = 2,
    }

    public class FlowStep
    {
        /// <summary>
        /// This is the special step to close the flow.
        /// </summary>
        public const int EndStepID = 0;

        #region properties

        public int FlowID
        {
            get;
            set;
        }

        /// <summary>
        /// The id of the step.
        /// </summary>
        public int ID
        {
            get;
            set;
        }

        /// <summary>
        /// The name of the step.
        /// </summary>
        public string Name
        {
            get;
            set;
        }

        /// <summary>
        /// The description of the step.
        /// </summary>
        public string Description
        {
            get;
            set;
        }

        /// <summary>
        /// 是否可以强制结束?
        /// </summary>
        public bool RightToFinish
        {
            get;
            set;
        }

        /// <summary>
        /// 流转规则
        /// </summary>
        public FlowRule FlowRule
        {
            get;
            set;
        }

        /// <summary>
        /// 指定会签的人数。如果为0，则不会签；如果小于0，则表示需要全体通过。
        /// </summary>
        public int PassNum
        {
            get;
            set;
        }

        /// <summary>
        /// Get the description text for <see cref="PassNum"/>.
        /// </summary>
        public string PassNumDescription
        {
            get
            {
                if (PassNum > 0)
                {
                    return string.Concat(PassNum.ToString(), "人会签");
                }
                if (PassNum == 0)
                {
                    return "不需要会签";
                }
                return "需全体通过！";
            }
        }

        /// <summary>
        /// 固定提醒
        /// </summary>
        public bool LocalAlert
        {
            get;
            set;
        }

        /// <summary>
        /// 基本时间
        /// </summary>
        public int BaseHour
        {
            get;
            set;
        }

        /// <summary>
        /// 循环次数
        /// </summary>
        public int CycTimes
        {
            get;
            set;
        }

        /// <summary>
        /// 周期
        /// </summary>
        public int Period
        {
            get;
            set;
        }

        /// <summary>
        /// 分支数量
        /// </summary>
        public int JumpCount
        {
            get;
            set;
        }

        #endregion

        #region methods

        /// <summary>
        /// Get all the steps defined for the given flow.
        /// </summary>
        public static IList<FlowStep> GetSteps(int flowId)
        {
            if (flowId <= 0)
            {
                throw new ArgumentOutOfRangeException("flowId");
            }

            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, flowId),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, 0), // specify zero to retrieve all steps for the flow.
            };

            var db = new Database();
            var list = new List<FlowStep>();
            using (var dr = db.RunDataReader("dbo.sproc_Flow_GetStep_V2", parameters))
            {
                while (dr.Read())
                {
                    list.Add(ReadFlowStep(dr));
                }
            }
            return list;
        }

        /// <summary>
        /// Get the information for the specified step.
        /// </summary>
        public static FlowStep GetStep(int flowId, int stepId)
        {
            if (flowId <= 0)
            {
                throw new ArgumentOutOfRangeException("flowId");
            }
            if (stepId <= 0)
            {
                throw new ArgumentOutOfRangeException("stepId");
            }

            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, flowId),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, stepId)
            };

            var db = new Database();
            using (var dr = db.RunDataReader("dbo.sproc_Flow_GetStep_V2", parameters))
            {
                if (dr.Read())
                {
                    return ReadFlowStep(dr);
                }
            }
            return null;
        }

        /// <summary>
        /// Get the formatted name of the specified step.
        /// </summary>
        public static string GetStepTitle(int flowId, int stepId)
        {
            var step = GetStep(flowId, stepId);
            if (step != null)
            {
                var sb = new StringBuilder();
                sb.Append("<span class=\"flow_step_title\" title=\"");
                sb.Append(HttpUtility.HtmlAttributeEncode(step.Description));
                sb.Append("\">");
                sb.Append(HttpUtility.HtmlEncode(step.Name));
                sb.Append("</span>");

                return sb.ToString();
            }

            return null;
        }

        /// <summary>
        /// Add a step for the specified flow, and returns the id of the added step.
        /// </summary>		
        /// <param name="StepName">步骤名</param>
        /// <param name="StepRemark">步骤简介</param>
        /// <param name="RightToFinish">是否有权利结束</param>
        /// <param name="FlowRule">流转规则</param>
        /// <param name="PassNum">会签数目</param>
        public static int AddStep(int FlowID, string StepName, string StepRemark, bool RightToFinish, FlowRule FlowRule, int PassNum, bool LocalAlert, int BaseHour, int CycTimes, int Period)
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, FlowID),
                Database.MakeInParam("@StepName", SqlDbType.NVarChar, 300, StepName),
                Database.MakeInParam("@StepRemark", SqlDbType.NText, -1, StepRemark),
                Database.MakeInParam("@RightToFinish", SqlDbType.Bit, 1, RightToFinish),
                Database.MakeInParam("@FlowRule", SqlDbType.Int, 4, (int)FlowRule),
                Database.MakeInParam("@PassNum", SqlDbType.Int, 4, PassNum),
                Database.MakeInParam("@LocalAlert", SqlDbType.Bit, 1, LocalAlert),
                Database.MakeInParam("@BaseHour", SqlDbType.Int, 4, BaseHour),
                Database.MakeInParam("@CycTimes", SqlDbType.Int, 4, CycTimes),
                Database.MakeInParam("@Period", SqlDbType.Int, 4, Period)
            };

            var db = new Database();
            return db.RunProc("dbo.sproc_Flow_AddStep_V2", parameters);
        }

        /// <summary>
        /// 修改步骤
        /// </summary>
        /// <param name="FlowID">流程ID</param>
        /// <param name="StepID">步骤ID</param>
        /// <param name="StepName">步骤名</param>
        /// <param name="StepRemark">步骤简介</param>
        /// <param name="RightToFinish">是否有权利结束</param>
        /// <param name="FlowRule">流转规则</param>
        /// <param name="PassNum">会签数目</param>
#pragma warning disable 1573
        public static int UpdateStep(int FlowID, int StepID, string StepName, string StepRemark, int RightToFinish, int FlowRule, int PassNum, int LocalAlert, int BaseHour, int CycTimes, int Period)
#pragma warning restore 1573
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, FlowID),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, StepID),
                Database.MakeInParam("@StepName", SqlDbType.NVarChar, 300, StepName),
                Database.MakeInParam("@StepRemark", SqlDbType.NVarChar, -1, StepRemark),
                Database.MakeInParam("@RightToFinish", SqlDbType.Bit, 1, RightToFinish),
                Database.MakeInParam("@FlowRule", SqlDbType.Int, 4, FlowRule),
                Database.MakeInParam("@PassNum", SqlDbType.Int, 4, PassNum),
                Database.MakeInParam("@LocalAlert", SqlDbType.Bit, 1, LocalAlert),
                Database.MakeInParam("@BaseHour", SqlDbType.Int, 4, BaseHour),
                Database.MakeInParam("@CycTimes", SqlDbType.Int, 4, CycTimes),
                Database.MakeInParam("@Period", SqlDbType.Int, 4, Period)
            };

            var db = new Database();
            return db.RunProc("dbo.sproc_Flow_UpdateStep_V2", parameters);
        }

        /// <summary>
        /// 删除步骤
        /// </summary>
        /// <param name="FlowID">被删除的步骤的流程ID</param>
        /// <param name="StepID">被删除的步骤的步骤ID</param>
        public static int DeleteStep(int FlowID, int StepID)
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, FlowID),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, StepID)
            };

            var db = new Database();
            return db.RunProc("dbo.sproc_Flow_DeleteStep_V2", parameters);
        }

        /// <summary>
        /// 上移步骤
        /// </summary>
        /// <param name="FlowID">流程ID</param>
        /// <param name="StepID">步骤ID</param>
        public static int MoveUpStep(int FlowID, int StepID)
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, FlowID),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, StepID)
            };

            using (var db = new Database())
            {
                return db.RunProc("dbo.sproc_Flow_MoveUpStep_V2", parameters);
            }
        }

        /// <summary>
        /// 得到流程的最大步骤
        /// </summary>
        /// <param name="FlowID">流程ID</param>
        /// <returns>最大步骤</returns>
        public static int GetMaxStep(int FlowID)
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, FlowID)
            };

            var db = new Database();
            return db.RunProc("dbo.sproc_Flow_GetMaxStep_V2", parameters);
        }

        #endregion

        #region help methods

        protected static void ReadFlowStep(IDataReader dr, FlowStep step)
        {
            step.FlowID = (int)dr["Flow_ID"];
            step.ID = (int)dr["Step_ID"];
            step.Name = Convert.ToString(dr["Step_Name"]);
            step.Description = Convert.ToString(dr["Step_Remark"]);
            step.RightToFinish = (bool)dr["RightToFinish"];
            step.FlowRule = (FlowRule)((int)dr["Flow_Rule"]);
            step.PassNum = (int)dr["PassNum"];
            step.LocalAlert = (bool)dr["LocalAlert"];
            step.BaseHour = (int)dr["BaseHour"];
            step.CycTimes = (int)dr["CycTimes"];
            step.Period = (int)dr["Period"];
            step.JumpCount = (int)dr["Jump_Count"];
        }

        private static FlowStep ReadFlowStep(IDataReader dr)
        {
            FlowStep s = new FlowStep();
            ReadFlowStep(dr, s);

            return s;
        }

        #endregion
    }
}
